package com.forest.datachangetracker.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;


/**
 * @author forest
 */
@Slf4j
@Component
public class MapperCacheManager implements ApplicationRunner {

    /**
     * 缓存结构：Entity类型 -> Mapper实例列表
     */
    private static final Map<Class<?>, List<Object>> ENTITY_MAPPER_CACHE = new ConcurrentHashMap<>();

    /**
     * 缓存结构：Mapper类型 -> Entity类型
     */
    private static final Map<Class<?>, Class<?>> MAPPER_ENTITY_CACHE = new ConcurrentHashMap<>();

    /**
     * 反向缓存：Mapper实例 -> Entity类型
     */
    private static final Map<Object, Class<?>> INSTANCE_ENTITY_CACHE = new ConcurrentHashMap<>();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        loadMapperCache();
    }

    private void loadMapperCache() {
        // 处理继承BaseMapper的接口
        loadBaseMappers();
        // 打印缓存信息
        printCacheInfo();
    }

    private void loadBaseMappers() {
        try {
            Map<String, BaseMapper> baseMappers = SpringUtil.getBeansOfType(BaseMapper.class);

            for (Map.Entry<String, BaseMapper> entry : baseMappers.entrySet()) {
                String beanName = entry.getKey();
                BaseMapper<?> mapperInstance = entry.getValue();

                // 获取Mapper接口类型
                Class<?> mapperInterface = getMapperInterface(mapperInstance);
                if (mapperInterface == null) continue;

                // 解析Entity类型
                Class<?> entityType = resolveEntityTypeFromBaseMapper(mapperInterface);
                if (entityType != null) {
                    cacheMapper(entityType, mapperInterface, mapperInstance, beanName);
                }
            }
        } catch (Exception e) {
            log.warn("加载BaseMapper失败: {}", e.getMessage());
        }
    }

    private Class<?> resolveEntityTypeFromBaseMapper(Class<?> mapperInterface) {
        // 解析BaseMapper的泛型参数
        Type[] genericInterfaces = mapperInterface.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType paramType = (ParameterizedType) genericInterface;
                if (paramType.getRawType().equals(BaseMapper.class)) {
                    Type[] typeArgs = paramType.getActualTypeArguments();
                    if (typeArgs.length > 0 && typeArgs[0] instanceof Class) {
                        return (Class<?>) typeArgs[0];
                    }
                }
            }
        }

        // 检查父接口
        for (Type superInterface : mapperInterface.getGenericInterfaces()) {
            if (superInterface instanceof Class) {
                Class<?> entityType = resolveEntityTypeFromBaseMapper((Class<?>) superInterface);
                if (entityType != null) return entityType;
            }
        }

        return null;
    }

    private Class<?> getMapperInterface(Object mapperInstance) {
        if (mapperInstance == null) return null;

        // 处理MyBatis代理对象
        if (mapperInstance.getClass().getName().contains("Proxy")) {
            Class<?>[] interfaces = mapperInstance.getClass().getInterfaces();
            for (Class<?> interfaceClass : interfaces) {
                if (interfaceClass.getName().contains("Mapper")) {
                    return interfaceClass;
                }
            }
        }

        return mapperInstance.getClass();
    }

    private void cacheMapper(Class<?> entityType, Class<?> mapperInterface,
                             Object mapperInstance, String beanName) {

        // 缓存 Entity -> Mapper实例列表
        ENTITY_MAPPER_CACHE
                .computeIfAbsent(entityType, k -> new CopyOnWriteArrayList<>())
                .add(mapperInstance);

        // 缓存 Mapper类型 -> Entity类型
        MAPPER_ENTITY_CACHE.put(mapperInterface, entityType);

        // 缓存 Mapper实例 -> Entity类型
        INSTANCE_ENTITY_CACHE.put(mapperInstance, entityType);

        log.debug("缓存Mapper: Entity={}, Mapper={}, Bean={}",
                entityType.getSimpleName(),
                mapperInterface.getSimpleName(),
                beanName);
    }


    public static List<Object> getMappersByEntity(Class<?> entityType) {
        return ENTITY_MAPPER_CACHE.getOrDefault(entityType, new ArrayList<>());
    }

    public static Class<?> getEntityByMapper(Class<?> mapperType) {
        return MAPPER_ENTITY_CACHE.get(mapperType);
    }

    public static Class<?> getEntityByMapperInstance(Object mapperInstance) {
        return INSTANCE_ENTITY_CACHE.get(mapperInstance);
    }

    public static Set<Class<?>> getAllCachedEntities() {
        return ENTITY_MAPPER_CACHE.keySet();
    }

    public static Map<Class<?>, List<Object>> getAllMappers() {
        return new HashMap<>(ENTITY_MAPPER_CACHE);
    }


    private void printCacheInfo() {
        log.info("=== Mapper缓存加载完成 ===");
        log.info("缓存Entity类型数量: {}", ENTITY_MAPPER_CACHE.size());

        for (Map.Entry<Class<?>, List<Object>> entry : ENTITY_MAPPER_CACHE.entrySet()) {
            Class<?> entityType = entry.getKey();
            List<Object> mappers = entry.getValue();
            log.info("Entity: {} -> {}个Mapper: {}",
                    entityType.getSimpleName(),
                    mappers.size(),
                    mappers.stream()
                            .map(mapper -> getMapperInterface(mapper).getSimpleName())
                            .collect(Collectors.toList()));
        }
        log.info("=========================");
    }
}
